package com.ywy.controller;

import cn.hutool.crypto.SecureUtil;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.ywy.common.rest.Result;
import com.ywy.entity.User;
import com.ywy.service.UserService;
import com.ywy.utils.ValidationUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * 用户认证Controller
 *
 * @author ywy
 * @date 2021/12/27 10:22
 */
@Controller
public class AuthController extends  BaseController {
    @Autowired
    private Producer producer;
    @Autowired
    private UserService userService;

    /**
     * 生成验证码
     * @param response
     * @throws IOException
     */
    @GetMapping("/captcha.jpg")
    public void captcha(HttpServletResponse response) throws IOException {
        // 响应头
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        // 生成文字验证码
        String text = producer.createText();
        // 生成图片验证码
        BufferedImage image = producer.createImage(text);

        // 把验证码存到shiro的session中
        req.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, text);

        ServletOutputStream outputStream = response.getOutputStream();
        ImageIO.write(image, "jpg", outputStream);
    }

    /**
     * 跳转用户登录页
     * @return
     */
    @GetMapping("/login")
    public String login() {
        return "auth/login";
    }

    /**
     * 跳转用户注册页
     * @return
     */
    @GetMapping("/register")
    public String register() {
        return "auth/register";
    }

    /**
     * 用户登录操作
     * @param email
     * @param password
     * @param vercode
     * @return
     */
    @ResponseBody
    @PostMapping("/login")
    public Result doLogin(String email, String password, String vercode) {
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {
            return Result.failure("邮箱或密码不能为空");
        }

        Object captcha = req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if (vercode == null || !vercode.equalsIgnoreCase(captcha.toString())) {
            return Result.failure("验证码输入不正确");
        }

        AuthenticationToken token = new UsernamePasswordToken(email, SecureUtil.md5(password));
        try {
            // 登录，调用realm的认证方法
            SecurityUtils.getSubject().login(token);
        } catch (AuthenticationException e) {
            if (e instanceof UnknownAccountException) {
                return Result.failure("用户不存在");
            } else if (e instanceof LockedAccountException) {
                return Result.failure("用户被禁用");
            } else if (e instanceof IncorrectCredentialsException) {
                return Result.failure("密码错误");
            } else {
                return Result.failure("用户认证失败");
            }
        }

        return Result.success("/index");
    }

    /**
     * 用户注册操作
     * @param user
     * @param vercode
     * @param repass
     * @return
     */
    @ResponseBody
    @PostMapping("/register")
    public Result doRegister(User user, String vercode, String repass) {
        // 校验参数
        ValidationUtil.ValidResult validResult = ValidationUtil.validateBean(user);
        if (validResult.isHasErrors()) {
            return Result.failure(validResult.getAllErrors());
        }
        if(!user.getPassword().equals(repass)) {
            return Result.failure("两次输入密码不一致");
        }
        Object captcha = req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if (vercode == null || !vercode.equalsIgnoreCase(captcha.toString())) {
            return Result.failure("验证码输入不正确");
        }

        Result result = userService.register(user);
        result.setData("/login");
        return result;
    }

    /**
     * 用户退出登录
     * @return
     */
    @GetMapping("/logout")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/login";
    }
}
